<template>
  <view class="sv-danmaku-track">
    <template v-for="(item, index) in dmlist" :key="item.id + index">
      <sv-danmaku-item v-if="item.alive" :item="item" @updateAalive="die"></sv-danmaku-item>
    </template>
  </view>
</template>

<script setup>
import { computed, nextTick, ref, watch } from 'vue'
import SvDanmakuItem from './sv-danmaku-item.vue'

const props = defineProps({
  container: {
    type: Object,
    default: () => ({})
  },
  list: {
	  type: Array,
	  default: []
  },
  dmDense: {
	  type: Number,
	  default: 2
  },
  speed: {
	  type: Number,
	  default: 5
  },
  loop: {
	  type: Boolean,
	  default: true
  }
})

const dmlist = ref([])
const activeDanmakus = ref([])
const danmakuContainer = ref({})

// 使用 watch 监听 container 变化
watch(() => props.container, (newValue) => {
  danmakuContainer.value = newValue
}, { immediate: true })


const handleDanmaku = (data) => {
  const { height } = danmakuContainer.value
  
  /**
   * 每条弹幕存活时长time
   * speed为速度1~5档，每档5s，1档时最慢，为25秒，5档最快，为5秒
   */
  const time = Math.ceil(25 / props.speed) // ceil向上取整 floor向下取整

  // 尝试找到一个不与其他弹幕重叠的位置
  let topPosition = findNonOverlappingTopPosition(height, activeDanmakus.value)

  let dmData = {
    ...data,
    time,
    style: {
      ...data.style,
      animationDuration: `${time}s`,
      top: `${topPosition}px`
    },
    danmakuContainer: danmakuContainer.value,
    alive: true // 装载后激活生命
  }

  // 添加弹幕到活动弹幕列表
  activeDanmakus.value.push(dmData)
  // 清理过期的弹幕
  cleanupExpiredDanmakus(activeDanmakus.value)

  return dmData
}

// 计算弹幕位置，尽量避免重叠
const findNonOverlappingTopPosition = (height, activeDanmakus, tolerance = 3) => {
  const maxAttempts = 60 // 最多尝试次数
  let attempts = 0
  let topPosition

  do {
    topPosition = Math.floor(Math.random() * (height - 30))
    attempts++

    // 检查是否与现有的弹幕重叠
    const isOverlapping = activeDanmakus.some((danmaku) => {
      const { style } = danmaku
      const danmakuTop = parseInt(style.top)
      return Math.abs(topPosition - danmakuTop) < 30 + tolerance // 尽量预留tolerance容错间隙
    })

    if (!isOverlapping) {
      break
    }
  } while (attempts < maxAttempts)

  // 如果尝试次数达到上限，随机选择一个位置
  if (attempts >= maxAttempts) {
    topPosition = Math.floor(Math.random() * (height - 30))
  }

  return topPosition
}

const add = (data) => {
  dmlist.value.push(handleDanmaku(data))
}

// 弹幕死亡手动销毁 - 已使用v-if="item.alive"处理 无需再手动清除
const die = (e) => {
  // 移除该释放的弹幕id
  // this.dmlist.some((item, index) => {
  //   if (item.id === e.id) {
  //     this.dmlist.splice(index, 1)
  //     return true
  //   }
  // })
  // console.log('==== 弹幕释放 :', e)
}

const clearDmlist = () => {
  dmlist.value = []
}

const cleanupExpiredDanmakus = (ads) => {
  // 清除过期的弹幕
  activeDanmakus.value = ads.filter((item) => item.alive)
}

const timer = ref()
const dmIndex = ref(0)
const timerMs = computed(() => Math.round(2000 / props.dmDense))

const stopTimer = () => {
	if (timer.value) {
	  clearInterval(timer.value)
	  timer.value = null
	}
}

const clearTimer = () => {
	stopTimer()
	dmIndex.value = 0
	clearDmlist()
}

const createTimer = () => {
	stopTimer()
	timer.value = setInterval(() => {
	  nextTick(() => {
	    // console.log('==== 发送弹幕 :', dmIndex.value, this.list[dmIndex.value])
	    add(props.list[dmIndex.value])
	    if (props.loop) {
	      // 开启弹幕循环
	      dmIndex.value = ++dmIndex.value > props.list.length - 1 ? 0 : dmIndex.value
	    } else {
	      // 关闭弹幕循环
	      dmIndex.value = ++dmIndex.value > props.list.length - 1 ? -1 : dmIndex.value
	    }
	    if (dmIndex.value == -1) {
	      // 关闭弹幕循环时，完成所有弹幕装填后需要停止timer，并重置索引
	      stopTimer()
	      dmIndex.value = 0
	    }
	  })
	}, timerMs.value)
}

// 暴露方法给父组件
defineExpose({
  createTimer
})
</script>

<style lang="scss">
.sv-danmaku-track {
  position: relative;
  width: 100%;
  height: 100%;
}
</style>